﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Office.Xoox.Spreadsheet;

namespace OpenSource.SpreadsheetFactory.Internal.Xlsx
{
    internal sealed class XlsxGenerator<T> : SpreadsheetGenerator<T>
    {
        public XlsxGenerator(IEnumerable<T> source)
            : base(source)
        {
        }

        internal override byte[] GenerateSpreadsheet()
        {
            return GetWorkbookBytes(CreateWorkbook());
        }

        private static byte[] GetWorkbookBytes(XSpreadsheet workbook)
        {
            byte[] result = null;

            using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
            {
                workbook.WriteTo(stream);
                stream.Seek(0, System.IO.SeekOrigin.Begin);

                using (System.IO.BinaryReader reader = new System.IO.BinaryReader(stream))
                {
                    result = reader.ReadBytes((int)stream.Length);
                    reader.Close();
                }
            }

            return result;
        }

        private XSpreadsheet CreateWorkbook()
        {
            XSpreadsheet workbook = new XSpreadsheet();
            CreateWorksheet(workbook);
            return workbook;
        }

        private void CreateWorksheet(XSpreadsheet workbook)
        {
            XWorksheet worksheet = workbook.Workbook.Sheets.AddWorksheet(Title);
            CreateHeader(worksheet);
            BuildBody(worksheet);
        }

        private void CreateHeader(XWorksheet worksheet)
        {
            int c = 0;

            foreach (Column<T> column in Columns)
            {
                c++;
                Reference cell = new Reference(1, c);

                worksheet[cell].SetContent(column.Title);
            }
        }

        private void BuildBody(XWorksheet worksheet)
        {
            int nextRow = 2;

            foreach (T item in base.Source)
            {
                int currentRow = nextRow++;
                int nextColumn = 1;
                foreach (Column<T> column in Columns)
                {
                    object value = column.GetColumnValue(item);

                    Reference cell = new Reference(currentRow, nextColumn++);

                    if (value is string)
                    {
                        worksheet[cell].SetContent(value as string);
                    }
                    else if (value is DateTime)
                    {
                        worksheet[cell].SetContent((DateTime)value);
                    }
                    else if (value is double)
                    {
                        worksheet[cell].SetContent((double)value);
                    }
                    else if (value is decimal)
                    {
                        worksheet[cell].SetContent((decimal)value);
                    }
                    else if (value is int)
                    {
                        worksheet[cell].SetContent((int)value);
                    }
                    else
                    {
                        worksheet[cell].SetContent(value.ToString());
                    }
                }
            }
        }
    }
}
